﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Facebook.Api;

namespace Facebook
{
    [Serializable]
    public partial class FacebookContextBase<TCache> : IFacebookContext, ISerializable
        where TCache : ICacheWrapper, new()
    {
        internal const String DEFAULT_VERSION = "1.0";

        public FacebookContextBase(String apiKey, String secret)
            : this(apiKey, secret, DEFAULT_VERSION) { }

        public FacebookContextBase(String apiKey, String secret, String version)
        {
            this.ApiKey = apiKey;
            this.Secret = secret;
            this.Version = version;
            this.Cache = new TCache();
        }

        private FacebookContextBase(SerializationInfo info, StreamingContext context)
            : this(info.GetString("ApiKey"), info.GetString("Secret"), info.GetString("Version"))
        {
            this.RequestCount = info.GetInt64("RequestCount");
            this.Session = (SessionInfo)info.GetValue("Session", typeof(SessionInfo));
        }

        public String ApiKey { get; internal set; }

        public String Secret { get; internal set; }

        public String Version { get; internal set; }

        public Int64 RequestCount { get; set; }

        public virtual SessionInfo Session { get; protected internal set; }

        public Boolean HasSession
        {
            get
            {
                if (this.Session == null) return false;
                return this.Session.Expires > DateTime.Now;
            }
        }

        protected internal ICacheWrapper Cache { get; set; }

        public IAsyncResult BeginExecuteRequest(String methodName, IDictionary<String, Object> args, AsyncCallback callback)
        {
            var request = new FacebookRequest(this, methodName, args);
            return request.BeginExecute(callback);
        }

        public FacebookResponse<TValue> EndExecuteRequest<TValue>(IAsyncResult result, String resposneXmlRoot)
        {
            return FacebookRequest.EndExecute<TValue>(result, resposneXmlRoot);
        }

        public FacebookResponse<TValue> ExecuteRequest<TValue>(String methodName, IDictionary<String, Object> args, String responseXmlRoot)
        {
            var request = new FacebookRequest(this, methodName, args);
            return request.Execute<TValue>(responseXmlRoot);
        }

        public virtual void HandleException(Exception ex)
        {
            throw ex;
        }

        public virtual ApplicationType ApplicationType { get; private set; }

        #region ISerializable Members

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("ApiKey", this.ApiKey);
            info.AddValue("Secret", this.Secret);
            info.AddValue("Session", this.Session);
            info.AddValue("Version", this.Version);
            info.AddValue("RequestCount", this.RequestCount);
        }

        #endregion
    }
}